package com.aaamvc.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.NotFoundException;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;

import org.apache.commons.beanutils.BeanUtils;

import com.aaamvc.xml.ActionBean;
import com.aaamvc.xml.ResultBean;

public class ReflectUtil {

	/**
	 * 
	 * @param actionName  userAction_save.do
	 * @param map              保存配置文件的Action
	 * @param reqMap         请求参数map用于封装到实体类
	 * @return
	 */
	public static ResultBean getResultBean(String actionName , 
			Map<String, ActionBean> map,
			Map reqMap,
			HttpServletRequest request,
			HttpServletResponse response){
		String [] actionInfo = actionName.split("_");
		ActionBean actionBean = map.get(actionInfo[0]);//userAction
		
		String clazz= actionBean.getClazz();
		ResultBean resultBean = null;
		try {
			Class actionClass = Class.forName(clazz);
			//创建Action对象
			Object object = actionClass.newInstance();
			
			//封装请求参数到Action属性
			bindingProperty(reqMap, object);
			
			//执行Action方法
			Method [] methods = actionClass.getMethods();
			Method invokeMethod = null;//准备调用的方法
			for (Method method : methods) {
				if (actionInfo[1].equals(method.getName())) {  //userAction_save
					invokeMethod = method;
				}
			}
			//解析参数
			//Class[] paraTypes= invokeMethod.getParameterTypes();
			//List paramList = bindingMethodParam(actionClass,reqMap,actionInfo[1],request,response);
			
			//System.out.println("paramList===========" + paramList);
			//String returnPath =  (String) invokeMethod.invoke(object,paramList.toArray());
			String returnPath =  (String) invokeMethod.invoke(object,null);
			List<ResultBean> results = actionBean.getResultBeans();
			for (ResultBean rsBean : results) {
				if (returnPath != null && returnPath.equals(rsBean.getName())) {
					resultBean = rsBean;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resultBean;
	}
	public static List bindingMethodParam(Class clazz,Map reqMap,String methodName,
			HttpServletRequest request,
			HttpServletResponse response){
		List paramList = new ArrayList();
		try {
			ClassPool pool = ClassPool.getDefault();
			pool.insertClassPath(new ClassClassPath(clazz));
			CtClass sp = pool.get(clazz.getName());
			
			CtMethod cm = sp.getDeclaredMethod(methodName);

			// 使用javaassist的反射方法获取方法的参数名
			MethodInfo methodInfo = cm.getMethodInfo();
			CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
			LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
			String[] paramNames = new String[cm.getParameterTypes().length];
			int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
			for (int i = 0; i < paramNames.length; i++)
			{
				paramNames[i] = attr.variableName(i + pos);
				String typeName = cm.getParameterTypes()[i].getName();
				//普通参数给参数赋值，
				if (reqMap.containsKey(paramNames[i])) {
					String values[] = (String[])reqMap.get(paramNames[i]);
					if (typeName.equals("int") || typeName.equals(Integer.class.getName()) ) {
						paramList.add(Integer.parseInt(values[0]));
					}
				}
				//非普通参数，request,response 直接传给Action方法
				if(typeName.equals("javax.servlet.http.HttpServletRequest")){
					paramList.add(request);
				}
				if(typeName.equals("javax.servlet.http.HttpServletResponse")){
					paramList.add(response);
				}
				System.out.println("==参数类型=" + cm.getParameterTypes()[i].getName());
				//如果是实体类，则遍历进行封装
				
			}
			
			// paramNames即参数名
			for (int i = 0; i < paramNames.length; i++) {
				System.out.println("==参数名称="+paramNames[i]);
			}

		} catch (NotFoundException e) {
			e.printStackTrace();
		}
		return paramList;
	}
	
	
	
	
	/**
	 * 封装请求参数
	 * @param reqMap      请求参数map
	 * @param object         Action对象
	 * @throws Exception
	 */
	public static void bindingProperty(Map reqMap, Object object)	throws Exception {
		Field [] fields = object.getClass().getDeclaredFields();
		for (int i=0; i<fields.length; i++) {
			Class  fieldClass =  fields[i].getType();
			Object fieldObject = null;
			Field[]  properyField =   fieldClass.getDeclaredFields();
			for (Field entityField : properyField) {  //实体类的属性
				if (reqMap.containsKey( entityField.getName() )) {
					if (fieldObject == null) {
						fieldObject = fieldClass.newInstance();
						BeanUtils.populate(fieldObject,reqMap);
						fields[i].setAccessible(true);
						fields[i].set(object, fieldObject);
						break;
					}
				}
			}
		}
	}
}
